#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "buffer.h"

Buffer * g_pbuf = NULL;

void Showusage();

int TestAppend();

int TestBatchAppend();

int TestGetByteBufferCopy();

int TestInsureSize();

int TestClear();

int TestGetRemainByteBuffer();

int TestBufferCopyConstruct();

int TestOperator();

int TestAll();

int main(int argc, char * argv[])
{
	int cmd = -1, ret = -1;
	
	if (argc<2)
	{
		Showusage();
		exit(-2);
	}
	
	cmd = atoi( argv[1] );
	
	switch (cmd)
	{
		case 1:
			ret = TestAppend();
			break;
		case 2:
			ret = TestBatchAppend();
			break;
		case 3:
			ret = TestGetByteBufferCopy();
			break;
		case 4:
			ret = TestInsureSize();
			break;
		case 5:
			ret = TestClear();
			break;
		case 6:
			ret = TestGetRemainByteBuffer();
			break;
		case 7:
			ret = TestBufferCopyConstruct();
			break;
		case 8:
			ret = TestOperator();
			break;	
		case 9:
			ret = TestAll();
			break;	
		default:
			printf("unknow cmd\n");
			Showusage();
			exit(-2);	
	}
	printf("ret %d\n",ret);
	return ret;
}

int TestAppend()
{
	int ret = -1;
	g_pbuf = new Buffer(256);
	g_pbuf->Append('a');
	g_pbuf->Append('b');
	if ( g_pbuf->GetByPos(0) != Buffer::GETC_ERROR && 
			g_pbuf->GetByPos(0) == 'a' )
	{
		if ( g_pbuf->GetByPos(1) != Buffer::GETC_ERROR && 
				g_pbuf->GetByPos(1) == 'b')
		{
			if ( g_pbuf->GetByPos(2) == Buffer::GETC_ERROR )
			{
				ret = 0;
			}
		}
	}
	delete g_pbuf;
	g_pbuf = NULL;
	return ret;
}


int TestBatchAppend()
{
	int ret = 0;
	g_pbuf = new Buffer(256);
	char temp[64] = {'1'};
	temp[63] = '\0';
	
	g_pbuf->Append(temp,sizeof(temp));
	
	if ( g_pbuf->GetLimit() != sizeof(temp) )
	{
		ret = -1;
	}
	else
	{
		for (int i=0; i<sizeof(temp); ++i)
		{
			if ( temp[i] != g_pbuf->GetByPos(i) )
			{
				ret = -1;
				break;
			}
		}
	}
	delete g_pbuf;
	g_pbuf = NULL;
	return ret;
}

int TestInsureSize()
{
	int ret = -1;
	char buf[10] = {'1'};
	char buf2[10] = {'2'};
	memset(buf, '1',10);
	memset(buf2, '2', 10);
	g_pbuf = new Buffer(16);

	g_pbuf->Append(buf,10);
	g_pbuf->Append(buf2,10);

	if ( 20 == g_pbuf->GetLimit() ) 
	{
		if ( '1' == g_pbuf->GetByPos(0) && '1' == g_pbuf->GetByPos(9) )
		{
			if ( '2' == g_pbuf->GetByPos(10) && '2' == g_pbuf->GetByPos(19) )
			{
				ret = 0;
			}
		}
	}
	else
	{
		printf("limit %d offset \n",g_pbuf->GetLimit() );
	}

	delete g_pbuf;
	g_pbuf = NULL;

	return ret;
}


int TestGetByteBufferCopy()
{
	int ret = 0;
	char buf[10] = {'1'};
	
	char * copy = NULL;
	int copyLen = -1;

	g_pbuf = new Buffer(16);

	g_pbuf->Append(buf,10);
	g_pbuf->GetByteBufferCopy(copy, copyLen);

	if ( copyLen == sizeof(buf) )
	{
		for ( int i=0; i<copyLen; ++i)
		{
			if ( buf[i] != g_pbuf->GetByPos(i) )
			{
				ret = -1;
				break;
			}
		}
	}
	else
	{
		ret = -1;
	}

	delete g_pbuf;
	g_pbuf = NULL;

	return ret;
}

int TestClear()
{
	int ret = -1;

	char buf[10] = {'1'};
	g_pbuf = new Buffer(16);

	g_pbuf->Append(buf,10);
	g_pbuf->Clear();

	if ( 0 == g_pbuf->GetOffset() && 0 == g_pbuf->GetLimit() )
	{
		ret = 0;
	}
	
	delete g_pbuf;
	g_pbuf = NULL;

	return ret;
}

int TestGetRemainByteBuffer()
{
	int ret = -1;

	char buf[10] = {'1'};
	g_pbuf = new Buffer(16);

	g_pbuf->Append(buf,10);

	char * be = g_pbuf->GetRemainByteBuffer();
	//cost 4bytes; 0,1,2,3 So, the current offset is 4
	g_pbuf->SetOffset(4);
	char * four = g_pbuf->GetRemainByteBuffer();
	if ( int (four - be) ==  4 )
	{
		ret = 0;
	}
	else
	{
		printf("four - begin address = %d \n", int(four-be));
	}
	
	delete g_pbuf;
	g_pbuf = NULL;

	return ret;
}

int help( Buffer buf )
{
	int ret = -1;
	printf( "global buf address %u, argument buf address %u\n",g_pbuf, &buf );
	if ( buf.GetLimit() == g_pbuf->GetLimit() )
	{
		if ( buf.GetOffset() == g_pbuf->GetOffset() )
		{
			strncpy( buf.GetByteBuffer(), g_pbuf->GetByteBuffer(), buf.GetLimit() );
			ret = 0;
		}
	}
	return ret;
}

int TestBufferCopyConstruct()
{
	g_pbuf = new Buffer();
	char t[] = {"12345455"};

	g_pbuf->Append( t, sizeof(t) );
	return help( *g_pbuf );
}

int TestOperator()
{

	g_pbuf = new Buffer();
	char t[] = {"12345455"};

	g_pbuf->Append( t, sizeof(t) );
	Buffer buf;
	buf = *g_pbuf;
	int ret = -1;
	
	if ( buf.GetLimit() == g_pbuf->GetLimit() )
	{
		if ( buf.GetOffset() == g_pbuf->GetOffset() )
		{
			for ( int i=0; i<buf.GetLimit(); ++i )
			{
				if ( buf.GetByPos(i) != g_pbuf->GetByPos(i) )
				{
					ret = -2;
					break;
				}
			}
			if ( ret != -2 )
				ret = 0;
		}
	}
	return ret;
}

void Showusage()
{
	printf("./testbuffer <mode> [a <test all>]\n");
	printf("\t -mode 1 test Append\n");
	printf("\t -mode 2 test batch Append\n");
	printf("\t -mode 3 test GetByteBufferCopy\n");
	printf("\t -mode 4 test InsureSize\n");
	printf("\t -mode 5 test Clear\n");
	printf("\t -mode 6 test GetRemainByteBuffer\n");
	printf("\t -mode 7 test BufferCopyConstruct\n");
	printf("\t -mode 8 test Operator\n");
	printf("\t -mode 9 test all\n");
}



int TestAll()
{
	int ret = -1;
	ret = TestAppend();
	if (ret == 0)
		ret = TestBatchAppend();
	if (ret == 0)
		ret = TestInsureSize();
	if (ret == 0)
		ret = TestGetByteBufferCopy();
	if (ret == 0)
		ret = TestClear();
	if (ret == 0)
		ret = TestGetRemainByteBuffer();
	if (ret == 0)
		ret = TestBufferCopyConstruct();
	if (ret == 0)
		ret = TestOperator();
	return ret;
}
